using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System;

public class SocketClient : MonoBehaviour
{

    private static string ip = "192.168.0.250";
    private static int port = 5690;
    private static Socket socketClient;

    // Start is called before the first frame update
    void Start()
    {
        CreateClient();
        ConnectServer();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            for (int i = 0; i < 20; i++)
            {
                string[] str = { "测试字符串1", "test1", "test11" };
                SendMessage(BuildDataPackage(1, 2, 3, 4, 5, str));
                string[] str2 = { "我是与1同时发送的测试字符串2，请注意我是否与其他信息粘包", "test2", "test22" };
                SendMessage(BuildDataPackage(1, 6, 7, 8, 9, str2));
            }
        }
    }

    private void OnApplicationQuit()
    {
        socketClient.Close();
    }

    /// <summary>
    /// 创建Socket实例对象
    /// </summary>
    void CreateClient()
    {
        socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    }

    /// <summary>
    /// 连接服务器
    /// </summary>
    void ConnectServer()
    {
        try
        {
            socketClient.Connect(IPAddress.Parse(ip), port);
        }
        catch (System.Exception e)
        {
            Debug.LogError(e.ToString());
            throw;
        }
    }

    void ReciveData()
    {
        while (true)
        {
            socketClient.Accept().BeginAccept(ReceiveMessage, socketClient);
        }
    }

    /// <summary>
    /// 构建消息数据包
    /// </summary>
    /// <param name="Crccode">消息校验码，判断消息开始</param>
    /// <param name="sessionid">用户登录成功之后获得的身份ID</param>
    /// <param name="command">主命令</param>
    /// <param name="subcommand">子命令</param>
    /// <param name="encrypt">加密方式</param>
    /// <param name="MessageBody">消息内容（string数组）</param>
    /// <returns>返回构建完整的数据包</returns>
    public static byte[] BuildDataPackage(int Crccode, long sessionid, int command, int subcommand, int encrypt, string[] MessageBody)
    {
        //消息校验码默认值为0x99FF
        Crccode = 65433;
        //消息头各个分类数据转换为字节数组（非字符型数据需先转换为网络序  HostToNetworkOrder:主机序转网络序）
        byte[] CrccodeByte = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(Crccode));
        byte[] sessionidByte = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(sessionid));
        byte[] commandByte = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(command));
        byte[] subcommandByte = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(subcommand));
        byte[] encryptByte = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(encrypt));
        //计算消息体的长度
        int MessageBodyLength = 0;
        for (int i = 0; i < MessageBody.Length; i++)
        {
            if (MessageBody[i] == "")
                break;
            MessageBodyLength += Encoding.UTF8.GetBytes(MessageBody[i]).Length;
        }
        //定义消息体的字节数组（消息体长度MessageBodyLength + 每个消息前面有一个int变量记录该消息字节长度）
        byte[] MessageBodyByte = new byte[MessageBodyLength + MessageBody.Length * 4];
        //记录已经存入消息体数组的字节数，用于下一个消息存入时检索位置
        int CopyIndex = 0;
        for (int i = 0; i < MessageBody.Length; i++)
        {
            //单个消息
            byte[] bytes = Encoding.UTF8.GetBytes(MessageBody[i]);
            //先存入单个消息的长度
            BitConverter.GetBytes(IPAddress.HostToNetworkOrder(bytes.Length)).CopyTo(MessageBodyByte, CopyIndex);
            CopyIndex += 4;
            bytes.CopyTo(MessageBodyByte, CopyIndex);
            CopyIndex += bytes.Length;
        }
        //定义总数据包（消息校验码4字节 + 消息长度4字节 + 身份ID8字节 + 主命令4字节 + 子命令4字节 + 加密方式4字节 + 消息体）
        byte[] totalByte = new byte[28 + MessageBodyByte.Length];
        //组合数据包头部（消息校验码4字节 + 消息长度4字节 + 身份ID8字节 + 主命令4字节 + 子命令4字节 + 加密方式4字节）
        CrccodeByte.CopyTo(totalByte, 0);
        BitConverter.GetBytes(IPAddress.HostToNetworkOrder(MessageBodyByte.Length)).CopyTo(totalByte, 4);
        sessionidByte.CopyTo(totalByte, 8);
        commandByte.CopyTo(totalByte, 16);
        subcommandByte.CopyTo(totalByte, 20);
        encryptByte.CopyTo(totalByte, 24);
        //组合数据包体
        MessageBodyByte.CopyTo(totalByte, 28);
        Debug.Log("发送数据包的总长度为：" + totalByte.Length);
        return totalByte;
    }

    ///<summary>
    ///发送信息
    ///</summary>
    public static void SendMessage(byte[] sendBytes)
    {
        //确定是否连接
        if (socketClient.Connected)
        {
            //获取远程终结点的IP和端口信息
            IPEndPoint ipe = (IPEndPoint)socketClient.RemoteEndPoint;
            socketClient.Send(sendBytes, sendBytes.Length, 0);
        }
    }


    private void ReceiveMessage(IAsyncResult ar)
    {
        /// <summary>
        /// 接收的大小
        /// </summary>
        int size = 0;
        //需要接收的大小
        byte[] recvBytes1 = new byte[28];
        //开始从数据缓存池中读取数据
        size = ((Socket)ar.AsyncState).Receive(recvBytes1, recvBytes1.Length, 0);
    }
}
